<?php

!defined('IN_VIFRAME') && die('Access Denied.');

class Log extends TLib {
	
	const
		LEVEL_ERROR       = 'ERROR',
		LEVEL_EXCEPTION   = 'EXCEPTION',
		LEVEL_INFO        = 'INFO';
	
	protected static
		$_Logs            = array(),
		$_Count           = 0,
		$_LevelFilters    = array(),
		$_CategoryFilters = array(),
		$_Id              = 1;

	public static function add($msg, $config = array()) {
		$config = self::_filterConfigParam($config, array(
			'Level'    => VI_LOG_LEVEL,
			'Category' => 'Script'
		));
		self::$_Logs[] = array(
			$config['Level'],
			$config['Category'],
			microtime(true) - VI_TIMER_BEGIN,
			$msg
		);
		++self::$_Count;
		
		return true;
	}

	public static function start($msg, $config = array()) {
		return self::add("Start: $msg", $config);
	}
	
	public static function end($msg, $config = array()) {
		return self::add("End: $msg", $config);
	}

	public static function get($config = array()) {
		$config   = self::_filterConfigParam($config, array(
			'Level'    => '',
			'Category' => ''
		));
		$levels   = $config['Level'];
		$category = $config['Category'];
		
		if(empty($levels) && empty($categories)) { // Have no filters
			return self::$_Logs;
		} elseif(empty($categories)) { // Have level filters
			self::$_LevelFilters    = preg_split('/[\s,]+/', strtoupper($levels), -1, PREG_SPLIT_NO_EMPTY);
			
			return array_values(array_filter(array_filter(self::$_Logs, array('self', '_filterByLevel'))));
		} elseif(empty($levels)) { // Have category filters
			self::$_CategoryFilters = preg_split('/[\s,]+/', $categories, -1, PREG_SPLIT_NO_EMPTY);
			
			return array_values(array_filter(array_filter(self::$_Logs, array('self', '_filterByCategory'))));
		} else { // Have both
			self::$_LevelFilters    = preg_split('/[\s,]+/', strtoupper($levels), -1, PREG_SPLIT_NO_EMPTY);
			self::$_CategoryFilters = preg_split('/[\s,]+/', $categories, -1, PREG_SPLIT_NO_EMPTY);
			
			$temp = array_values(array_filter(array_filter(self::$_Logs, array('self', '_filterByLevel'))));
			return array_values(array_filter(array_filter($temp, array('self', '_filterByCategory'))));
		}
	}

	protected static function _filterByLevel($log) {
		return in_array(strtoupper($log[0]), self::$_LevelFilters) ? $log : false;
	}

	protected static function _filterByCategory($log) {
		$value = $log[1];
		foreach(self::$_CategoryFilters as $category) {
			if(($value == $category)
				|| ((($temp = rtrim($category,'.*')) !== $category) && (strpos($value,$temp) === 0))) {
				return $log;
			}
		}
		
		return false;
	}

	public static function count() {
		return self::$_Count;
	}

	public static function flush($config = array()) {
		Vi::checkClassExist('OSystemMessage');
		
		$config   = self::_filterConfigParam($config, array(
			'Level'    => '',
			'Category' => '',
			'Die'      => false
		));
				
		$logs    = self::get($config['Level'], $config['Category']);
		$count   = count($logs);
		$output  = '';
		
		$sysMsg  = new OSystemMessage('ViFramework Log');
		$sysMsg->appendProperty('LogID', self::$_Id, 16, 1)
		       ->appendProperty('LevelFilters', $levels)
		       ->appendProperty('CategoryFilters', $categories)
		       ->appendProperty('Count', $count)
		       ->appendSeparator();
		
		$id = 0;
		foreach ($logs as $log) {
			$log[2] *= 1000;
			++$id;
			
			$sysMsg->appendSubtitle("Id - $id", 1)
		           ->appendProperty('Level', "LOG_{$log[0]}", 9, 2)
		           ->appendProperty('Category', $log[1], 9, 2)
		           ->appendProperty('Time', $log[2].' (ms)', 9, 2)
		           ->appendProperty('Msg', $log[3], 9, 2)
		           ->appendLine();
		}
		
		$sysMsg->appendSeparator()
		       ->flush($config['Die']);

		++self::$_Id;
		
		return true;
	}
} 